package xyz.app.queries;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import lombok.NonNull;
import xyz.app.AbstractDomain;

import java.util.Map;
import java.util.Optional;

public interface WhereEqualsOrNull<T extends AbstractDomain> {

    @NonNull CriteriaBuilder builder();

    @NonNull Root<? extends T> root();

    default @NonNull Predicate[] getPredicateEqualsOrNull(@NonNull Map<@NonNull String, Object> values) {
        return values.entrySet().stream()
                .map(e -> getPredicateEqualsOrNull(e.getKey(), e.getValue()))
                .toArray(Predicate[]::new);
    }

    default <V> @NonNull Predicate getPredicateEqualsOrNull(@NonNull String name, V value) {
        return Optional.ofNullable(value)
                .filter(val -> !(val instanceof String s) || !s.isBlank())
                .map(val -> builder().equal(root().<V>get(name), val))
                .orElseGet(() -> builder().isNull(root().<V>get(name)));
    }

    <V> @NonNull WhereEqualsOrNull<T> whereEqualsOrNull(@NonNull String name, V value);

    @NonNull WhereEqualsOrNull<T> whereEqualsOrNull(@NonNull Map<@NonNull String, Object> values);
}